#pragma once
#include "Common.h"
#include "ThreadCache.h"
#include "PageCache.h"
#include "ObjectPool.h"

static void* ConcurrentAlloc(size_t size)
{
	// 大于一定量级申请时：
	if (size > MAX_BYTES) // BUG(MAXBYTES)
	{
		// 先对齐
		size_t alignSize = SizeClass::RoundUp(size);
		// 再找PageCache new一个span出来
		size_t kpage = alignSize >> PAGE_SHIFT;

		// BUG调试
		/*if (kpage == 0)
		{
			int x = 0;
		}*/

		// 访问PageCache要加锁，因为他可能会访问到内部的哈希桶
		PageCache::GetInstance()->GetMtx().lock();
		Span* span =  PageCache::GetInstance()->NewSpan(kpage);
		span->_objSize = size;
		PageCache::GetInstance()->GetMtx().unlock();

		void* ptr = (void*)(span->_pageId << PAGE_SHIFT);
		return ptr;
	}
	else
	{
		// 通过TLS 每个线程无锁的获取自己专属的ThreadCache对象
		if (pTLSThreadCache == nullptr)
		{
			//pTLSThreadCache = new ThreadCache;

			static ObjectPool<ThreadCache> tcPool;
			pTLSThreadCache = tcPool.New();
		}

		// cout << std::this_thread::get_id() << ": " << pTLSThreadCache << endl;

		return pTLSThreadCache->Allocate(size);
	}
}

static void ConcurrentFree(void* ptr)
{
	// 这个待会单独加锁
	Span* span = PageCache::GetInstance()->MapObjectToSpan(ptr);
	size_t size = span->_objSize;

	if (size > MAX_BYTES)
	{
		PageCache::GetInstance()->GetMtx().lock();
		PageCache::GetInstance()->ReleaseSpanToPageCache(span);
		PageCache::GetInstance()->GetMtx().unlock();

	}
	else
	{
		assert(pTLSThreadCache);
		pTLSThreadCache->Deallocate(ptr, size);
	}

	
}